package cn.biplam.back.operator.tree;

import java.util.ArrayList;

import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.client.Operator;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.interfaces.DataOperator;
import cn.biplam.common.opcode.SysManageCode.TreeIndexCode;
import cn.biplam.common.paramters.TreeParam.Index_Tree_Node_Type;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;
import cn.biplam.common.wrapper.tree.TreeIndexFields;

/**
 * 索引表操作类<br>
 * <li> 所有索引表的数据操作必须传入表名称作为参数 
 * @author WangSong 2009-6-5下午07:57:37
 * @version 1.0
 */
public class OptTreeIndex extends DataOperator {

	public OptTreeIndex() throws ErrorMessage {
		super();//从Filter里传入
	}
	
	public OptTreeIndex(String userId,DbResource dbResource) throws ErrorMessage {
		super();
		this.userId=userId;
		this.dbResource=dbResource;
	}

	/**
	 * 直接调用初始化方法
	 * @param userId
	 * @param result
	 * @param opId
	 * @param dbResource
	 * @throws ErrorMessage
	 */
	public OptTreeIndex(String userId,OperatorResult result,String opId,DbResource dbResource) throws ErrorMessage {
		super("noname");
		this.userId=userId;
		this.result=result;
		this.opId=opId;
		this.dbResource=dbResource;
	}

	private TreeIndexFields fields = null;
	protected static final String TABLE_NAME = "table_name";

	@Override
	protected OperatorResult _exchange() throws ErrorMessage {
		ArrayList<String> sql = new ArrayList<String>();
		if(opId.equals(TreeIndexCode.Select_Flat_Node)){
			this.getFlatNode(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Select_Node)){
			this.getNodeById(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Select_Sub_Tree_Depth)){
			this._getTreeDepth(sql,filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Get_Numb_Of_Child)){
			this._getImmediateChildNumber(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Insert_Index_Node)){
			this.insertNode(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Insert_By_Index_Id)){
			this.insertFirst(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Insert_Root)){
			this.insertFirst(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Insert_Virtual_Root)){
			this._insertVirtualNode(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Insert_First)){
			this.insertFirst(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Insert_Second)){
			this.insertSecond(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Update_Index_Node)){
			this.update(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Update_By_Rel_ID)){
			this.updateByRelId(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Select_Sub_Tree)){
			this._getChildren(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Select_By_Rel_ID)){
			this.getNodeByRelId(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Select_Node_Parents)){
			this.getNodeParents(sql, filter);
			return this.result;
		}else if(opId.equals(TreeIndexCode.Select_Path)){
			this.getNodePath(sql, filter);
			return this.result;
		}else if(opId.equals(TreeIndexCode.Get_Nearest_Node)){
			this.getNearestNode(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Move_Node)){
			this.moveNode(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Move_By_Index_Id)){
			this.moveNodeByIndexId(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Get_Immediate_Children)){
			this._getImmediateChild(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else if(opId.equals(TreeIndexCode.Delete_Root_Node)){
			this.deleteRoot(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Delete_Root_By_Index_Id)){
			this.deleteRootByIndexId(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Delete_By_Index_Id)){
			this.deleteNodeByIndex(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Delete_Virtual_Root)){
			this.deleteVirtualNode(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Delete_Index_Node)){
			this.deleteNode(sql, filter);
			return this.doing(sql, Operator_Type.DML);
		}else if(opId.equals(TreeIndexCode.Query_Child_Theme)){
			this.getChildTheme(sql, filter);
			return this.doing(sql, Operator_Type.Select);
		}else{
			throw new ErrorMessage("OptExpIndex Operator Exchange outport not found:"+ opId+" !");
		}
	}

	/**
	 * 获取指定节点的子节点
	 *           <P>过滤器参数包括：<BR>节点ID <BR>
	 *          			  节点类型(Operator_Type)<BR>
	 *          			  节点索引类型(Node_Type)<BR>
	 *                        向下查询子节点的级数(level_down)：-1 全部 1向下1级,2向下2级,n向下n级<BR></P>
	 */
	private void _getChildren(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		String nodeId=filter.getValue(this.fields.getNodeId());
		String nodeType=filter.getValue(this.fields.getNodeType());
		String operatorType = filter.getValue(this.fields.getOperatorType());
		int levelDown=TOOLS.stringToInt(filter.getValue("level_down"));
		int depth=_getSubTreeDepth(nodeId,nodeType,filter);//获取当前节点为根节点的子树的深度
		//计算向下查询的级数
		if(levelDown==-1){
			levelDown=depth;
		}else{
			levelDown=levelDown>depth?depth:levelDown;
		}
		//获取查询SQL
		StringBuilder sp=new StringBuilder();
		StringBuilder subSql = new StringBuilder();
		this.getTreeSql(subSql, levelDown, nodeId, nodeType , operatorType);
		if(!"".equals(subSql.toString().trim())){
			sp.append(" select * from (");
			sp.append(subSql.toString());
			sp.append(") a where ");
			sp.append(fields.getNodeId()+"<>'"+nodeId+"'  ");
			sp.append(" order by "+fields.getNodeLevel()+","+fields.getNodeSequence());
			sql.add(sp.toString());
		}
	}

	/**
	 * 获取离指定节点最近的节点，如果节点没有兄弟则最近为节点的父亲，如果有哥哥节点则最近为哥哥，如果无哥哥节点则最近为弟弟
	 * @param sql    
	 * @param filter 过滤器 参数：当前节点ID
	 * @throws ErrorMessage 
	 */
	public void getNearestNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeSelect(this.userId,this.tableName,this.fields,this.dbResource).
			getNearestNode(sql, filter);
	}

	/**
	 * 获取指定节点的平面化信息
	 * @param sql   查询SQL容器
	 * @param filter 查询过滤器，过滤器内容包括：节点ID，节点级别，节点类型，节点的父亲们是否有弟弟
	 * @throws ErrorMessage 
	 */
	public void getFlatNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		String nodeId=filter.getValue(this.fields.getNodeId());
		int depth=0;
		String nodeType=filter.getValue(this.fields.getNodeType());
		String operatorType = filter.getValue(this.fields.getOperatorType());
		StringBuilder sp=new StringBuilder();
		sp.append(" select * from (");
		this.getTreeSql(sp, depth, nodeId, nodeType,operatorType);
		sp.append(") a");
		sql.add(sp.toString());
	}

	/**
	 * 根据节点物理表ID获取节点
	 * @throws ErrorMessage 
	 */
	public void getNodeByRelId(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		String nodeRelId=filter.getValue(this.fields.getRealId());
		StringBuilder sp=new StringBuilder();
		sp.append(" select * from "+this.tableName);
		sp.append(" where "+this.fields.getRealId()+"='"+nodeRelId+"'");
		sql.add(sp.toString());
	}

	/**
	 * 根据索引节点ID移动
	 * @param filter 传入被移动节点的物理表ID和移动到的节点物理表ID<br>
	 * 				 <ul>需要参数： 
	 * 					  <li>moved_node_id 被移动节点ID 	
	 *                	  <li>move_to_node_id 移动到节点ID
	 *                    <li>move_type 移动类型
	 *               </ul>
	 * @throws ErrorMessage 未指定移动类型抛出异常
	 */
	private void moveNodeByIndexId(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeMove(this.userId,this.tableName,this.fields,this.dbResource).moveNodeByIndexId(sql, filter);
	}

	/**
	 * 根据索引节点对应真实ID移动<font color='red'><B>不建议使用,目前在模型管理索引表中使用</B></font>
	 * @param filter 传入被移动节点的物理表ID和移动到的节点物理表ID<br>
	 * 				 <ul>需要参数： 
	 * 					  <li>moved_node_id 被移动节点ID 	
	 *                <li>move_to_node_id 移动到节点ID
	 *                <li>move_type 移动类型
	 *           </ul>
	 * @throws ErrorMessage 未指定移动类型抛出异常
	 */
	public void moveNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeMove(this.userId,this.tableName,this.fields,this.dbResource).moveNode(sql, filter);
	}

	/**
	 * 根据节点ID获取节点
	 * @throws ErrorMessage 
	 */
	public void getNodeById(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		String nodeId=filter.getValue(this.fields.getNodeId());
		new OptIndexTreeSelect(this.userId,this.tableName,this.fields,this.dbResource).
		getNodeById(sql, nodeId);
	}

	/**
	 * 获取指定节点的所有父节点ID
	 * @param sql    sql容器
	 * @param filter 查询条件 参数：节点ID，节点级别
	 * @throws ErrorMessage 
	 */
	private void getNodeParents(ArrayList<String>  sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		KvMap<String, String> parents = new KvMap<String, String>();
		OperatorResult mParent = Operator.get(TreeIndexCode.Select_Node, userId, filter);
		String curParent = null;
		while(TOOLS.exist(mParent)){
			curParent = mParent.getValue(this.fields.getNodeParent());
			parents.put(curParent, curParent);
			filter.put(this.fields.getNodeId(), curParent);
			mParent = Operator.get(TreeIndexCode.Select_Node, userId, filter);
		}
		this.result.setKvResult(parents);
	}

	/**
	 * 获取指定节点之间的路径
	 * @param sql    sql容器
	 * @param filter 查询条件 参数：节点ID（起始节点） 父亲节点ID(终止节点)
	 *               返回： 起始节点和终止节点之间的起始节点的所有父亲
	 * @throws ErrorMessage 
	 */
	private void getNodePath(ArrayList<String>  sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		//存储所有父亲节点的列表容器
		ArrayList<String> parents = new ArrayList<String>();
		//查询当前节点
		OperatorResult mParent = Operator.get(TreeIndexCode.Select_Node, userId, filter);
		//终止节点
		String endParentId = filter.getValue(this.fields.getNodeParent());
		String curParent = null;
		//如果节点存在父亲继续查询
		while(TOOLS.exist(mParent)){
			//如果当前节点为根节点终返回节点到根节点的路径
			String operatorType = mParent.getValue(this.fields.getOperatorType());
			if(operatorType.equals(Index_Tree_Node_Type.ROOT_THEME.toString())){
				break;
			}
			//将当前节点的父亲加入到父亲列表
			curParent = mParent.getValue(this.fields.getNodeParent());
			parents.add(curParent);
			//如果当前节点的父亲为终止节点推出查询,返回节点间路径
			
			if(curParent.equals(endParentId)){
				break;
			}
			//查询节点的父亲的父亲
			filter.put(this.fields.getNodeId(), curParent);
			mParent = Operator.get(TreeIndexCode.Select_Node, userId, filter);
		}
		//返回节点间路径
		this.result.setListResult(parents);
	}

	/**
	 * 	
	 *  获取第一次插入节点的SQL(不适用于虚拟根节点)<BR>
	 *  用于:普通节点或者根节点插入(普通节点插入必须传入父节点索引ID,根节点插入建议传入父节点索引ID) <BR>
	 *  <P>参数:节点类型 (OperatorType), [节点ID],[父节点索引ID(使用NODE_PARENT名称传参)],[名称]、[描述]、[节点真实ID]、[index] <BR>
	 *      <B>节点类型为必须传入参数</B><BR></P>
	 */
	public void insertFirst(ArrayList<String> sql,
			DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		OptIndexTreeInsert insert = 
			new OptIndexTreeInsert(this.userId,this.tableName,this.fields,this.dbResource);
		//设置当前插入的节点ID
		this.result.setLastRowId(insert.insertFirst(sql, filter));
		//设置当前插入节点的排序号
		this.result.setStrResult(String.valueOf(insert.getCurentSequence()));
	}
	
	/**
	 *  <ul>  获取非第一次插入节点的SQL(不适用于虚拟根节点)
	 *    <li>适用条件:获取批量插入节点SQL时插入当前级别非第一个节点
	 *    <li>参数:节点类型 (OperatorType),sequence(前一节点的排序号),[哥哥节点类型](参数名为preOperator_Type),
	 *    			[父节点ID],[节点ID],[名称]、[描述]、[节点真实ID]、[index] <BR>
	 *            <B> sequence为必传字段,父亲节点ID为必传字段</B><BR>
	 *  </ul>
	 */
	public void insertSecond(ArrayList<String> sql,
			DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		OptIndexTreeInsert insert = 
			new OptIndexTreeInsert(this.userId,this.tableName,this.fields,this.dbResource);
		//设置当前插入的节点ID
		this.result.setLastRowId(insert.insertSecond(sql, filter));
		//设置当前插入节点的排序号
		this.result.setStrResult(String.valueOf(insert.getCurentSequence()));
	}
	
	/**
	 * 传入父亲真实ID插入节点<BR><font color='red'>(不建议使用,目前只在模型索引树使用)</font><BR>
	 *  参数:<BR>父节点真实ID(使用NODE_PARENT名称传参),[节点ID],[节点类型](OperatorType),[名称],[描述],[节点真实ID],[index]<BR>
	 * @throws ErrorMessage 
	 */
	public void insertNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		OptIndexTreeInsert insert = 
			new OptIndexTreeInsert(this.userId,this.tableName,this.fields,this.dbResource);
		//设置当前插入的节点ID
		this.result.setLastRowId(insert.insertByParentRealId(sql, filter));
		//设置当前插入节点的排序号
		this.result.setStrResult(String.valueOf(insert.getCurentSequence()));
	}

	/**
	 *  插入虚拟根节点<BR>
	 *  <P>参数: [节点ID],[节点名称],[节点描述] <BR>
	 *         <B>全为可选参数,如果不传入节点ID自动生成节点ID</B></P>
	 */
	private void _insertVirtualNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		OptIndexTreeInsert insert = 
			new OptIndexTreeInsert(this.userId,this.tableName,this.fields,this.dbResource);
		this.result.setLastRowId(insert.insertVirtualNode(sql, filter));
	}

	/**
	 *  根据索引节点ID删除根节点
	 */
	private void deleteRootByIndexId(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeDelete(this.userId,this.tableName,this.fields,this.dbResource).deleteRootByIndexId(sql, filter);
	}

	/**
	 * 根据节点对应真实ID删除根节点
	 */
	public void deleteRoot(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeDelete(this.userId,this.tableName,this.fields,this.dbResource).deleteRoot(sql, filter);
	}

	/**
	 *  根据节点ID删除虚根节点<BR>
	 *  参数： 节点ID
	 */
	private void deleteVirtualNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		//初始化索引表名称
		_initTableFields(filter);
		new OptIndexTreeDelete(this.userId,this.tableName,this.fields,this.dbResource).deleteVirtualNode(sql, filter);
	}

	/**
	 *  根据索引ID删除节点
	 *  参数: 索引节点ID
	 */
	private void deleteNodeByIndex(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeDelete(this.userId,this.tableName,this.fields,this.dbResource).deleteNodeByIndex(sql, filter);
	}

	/**
	 * 根据真实ID删除节点<BR><B>提供给模型索引表使用,其他表不建议使用</B>
	 * @param filter 参数: 节点真实ID
	 */
	public void deleteNode(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		new OptIndexTreeDelete(this.userId,this.tableName,this.fields,this.dbResource).deleteNode(sql, filter);
	}

	/**
	 * 根据节点ID更新节点内容
	 * @param filter   参数: 节点ID, [节点名]、[节点描述]、[节点类型]
	 * @throws ErrorMessage 
	 */
	public void update(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		_update(sql, filter);
	}

	/**
	 * 根据节点的真实ID更新节点内容<BR><B>提供给模型索引表使用,其他表不建议使用</B>
	 * @param filter  参数: 节点真实, [节点名]、[节点描述]、[节点类型]
	 * @throws ErrorMessage
	 */
	public void updateByRelId(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		_update(sql, filter);
	}

	/**
	 * 更新节点内容
	 * @param filter 更新节点的内容包括：节点名、节点描述、节点类型
	 */
	private void _update(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		new IndexTree(userId,this.tableName,this.fields,this.dbResource).update(sql, filter);
	}

	/**
	 * 查询当前节点是否有子指定级数的节点，如指定1级则返回是否有下一级节点、如果指定2级则返回是否有下两级节点 依次类推...
	 * @param sql
	 * @param filter 过滤参数： 节点类型、要向下查询的级数
	 * @throws ErrorMessage 
	 */
	private void _getTreeDepth(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		StringBuilder sp=new StringBuilder();
		String nodeType=filter.getValue(this.fields.getNodeType());
		String operatorType = filter.getValue(this.fields.getOperatorType());
		int levelDown=TOOLS.stringToInt(filter.getValue("depth"));
		if(levelDown==-1){
			levelDown=1;
		}
		sp.append("select 1 ");
		sp.append(" from "+this.tableName+" a1");
		int j;
		for(j=1;j<=levelDown;j++){
			sp.append(" join "+tableName+" a"+(j+1));
			sp.append(" on a"+(j)+"."+fields.getNodeId()+"=a"+(j+1)+"."+fields.getNodeParent()+" ");
		}
		sp.append("where a1."+fields.getNodeId()+"='"+filter.getValue(this.fields.getNodeId())+"'");
		if(nodeType!=null){
			sp.append(" and a"+(j)+"."+fields.getNodeType()+"='"+nodeType+"'");
		}
		if(operatorType!=null){
			sp.append(" and a"+(j)+"."+fields.getOperatorType()+"<'"+operatorType+"'");
		}
		sql.add(sp.toString());
	}

	/**
	 * 获取指定节点的子节点级数，即指定节点为根节点时子树深度 
	 */
	private int _getSubTreeDepth(String nodeId,String nodeType,DataFilter filter) throws ErrorMessage{
		SqlResult sr=Operator.get(TreeIndexCode.Select_Sub_Tree_Depth, this.userId, filter).getSelectResult();
		int depth=0;
		while(sr!=null&&!sr.isNull()){
			++depth;
			filter.put("depth",TOOLS.intToString(depth));
			sr=Operator.get(TreeIndexCode.Select_Sub_Tree_Depth, this.userId, filter).getSelectResult();
		}
		return depth-1;
	}

	/**
	 * 获取指定节点的直属子节点数量
	 * @param sNodeId 节点ID 
	 * @return 指定节点的直属子节点数
	 * @throws ErrorMessage
	 */
	private void _getImmediateChildNumber(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		StringBuilder sp=new StringBuilder();
		sp.append("select count(1) from ");
		sp.append(this.tableName);
		sp.append(" where ");
		sp.append(this.fields.getNodeParent());
		sp.append("='");
		sp.append(filter.getValue(this.fields.getNodeId()));
		sp.append("' ");
		//如果传入了节点索引类型根据类型过滤(在模型索引树中使用)
		String nodeType = filter.getValue(this.fields.getNodeType());
		if(nodeType!=null){
			sp.append(" and ");
			sp.append(this.fields.getNodeType());
			sp.append("='");
			sp.append(nodeType);
			sp.append("' ");
		}
		sql.add(sp.toString());
	}

	/**
	 * 获取指定节点的直属子节点
	 * @param filter  参数<BR>
	 *         NodeId(节点ID),[operatorType(节点类型)],[nodeType(节点索引)]<BR>
	 *         如果过滤器包含节点类型,返回指定节点类型的子节点<BR>
	 * @return 指定节点的直属子节点
	 * @throws ErrorMessage
	 */
	private void _getImmediateChild(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		StringBuilder sp=new StringBuilder();
		sp.append("select *  from ");
		sp.append(this.tableName);
		sp.append(" where ");
		sp.append(this.fields.getNodeParent());
		sp.append("='");
		sp.append(filter.getValue(this.fields.getNodeId()));
		sp.append("' ");
		//如果传入了节点索引类型根据类型过滤(在模型索引树中使用)
		String nodeType = filter.getValue(this.fields.getNodeType());
		if(nodeType!=null){
			sp.append(" and ");
			sp.append(this.fields.getNodeType());
			sp.append("='");
			sp.append(nodeType);
			sp.append("' ");
		}
		//如果根据类型获取子节点,返回同种类型的子节点
		String operatorType = filter.getValue(this.fields.getOperatorType());
		if(operatorType!=null){
			sp.append(" and ");
			sp.append(this.fields.getOperatorType());
			sp.append("='");
			sp.append(operatorType);
			sp.append("' ");
		}
		sp.append(" order by ");
		sp.append(this.fields.getNodeSequence());
		sql.add(sp.toString());
	}

	/**
	 *  获取指定节点下的子主题(逆序排列,序号最大的在最前面)<BR>
	 *  参数：table_name,node_id
	 */
	private void getChildTheme(ArrayList<String> sql,DataFilter filter) throws ErrorMessage{
		_initTableFields(filter);
		StringBuilder sp=new StringBuilder();
		sp.append("select *  from ");
		sp.append(this.tableName);
		sp.append(" where ");
		sp.append(this.fields.getNodeParent());
		sp.append("='");
		sp.append(filter.getValue(this.fields.getNodeId()));
		sp.append("' and ");
		sp.append(this.fields.getOperatorType());
		sp.append(" = '");
		sp.append(Index_Tree_Node_Type.UN_ROOT_THEME);
		sp.append("'");
		sp.append(" order by ");
		sp.append(this.fields.getNodeSequence());
		sp.append(" desc ");
		sql.add(sp.toString());
	}
	
	/**
	 *  获取查询树数据SQL
	 */
	private void getTreeSql(StringBuilder sp,int levelDown,String nodeId
			,String nodeType,String operatorType){
		new OptIndexTreeSelect(this.userId,this.tableName,this.fields,this.dbResource).
		getTreeSql(sp, levelDown, nodeId, nodeType, operatorType);
	}

	/**
	 * 根据传入过滤器初始化树形表表名和树形表表字段映射关系
	 * @param filter 过滤器
	 * @throws ErrorMessage 如果过滤器未传入表名抛出异常，如果表名不存在表字段映射关系抛出异常 
	 */
	private void _initTableFields(DataFilter filter) throws ErrorMessage{
		String tableName=filter.getValue("table_name");
		if(tableName==null||"".endsWith(tableName)){
			throw new ErrorMessage("Do not have appointed table!");
		}
		this.tableName=tableName;
		this.fields=TreeIndexFields.getTreeFields(tableName);
		if(this.fields==null){
			throw new ErrorMessage("Do not exist reflection with table "+tableName+"!");
		}
	}
}
